﻿#region Copyright(C) 2018 FI Ltd. All rights reserved.

// ==================================================================================================
// Copyright(C) 2018 FI Ltd. All rights reserved.
//
// SYSTEM NAME	:   FI.Net Application Framework 
// COMPONENT ID :   FI.EntityFramework
// COMPONENT DESC:  
//
// CREATED DATE/BY: 18 Aug 2018 / Tian Mi
//
// REVISION HISTORY:	DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Linq.Expressions;

namespace FI.EntityFramework
{
    /// <summary>
    /// Class Repository
    /// </summary>
    /// <typeparam name="TEntity">The type of the T entity.</typeparam>
    /// <typeparam name="TDbContext">The type of the T db context.</typeparam>
    public abstract class Repository<TEntity, TDbContext> : RepositoryBase<TDbContext>
        where TEntity : class
        where TDbContext : DbContext
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Repository&lt;TEntity, TDbContext&gt;"/> class.
        /// </summary>
        /// <param name="dbContext">The db context.</param>
        public Repository(TDbContext dbContext)
            : base(dbContext)
        {
#if DEBUG
            this.DbContext.Database.Log = this.WriteLog;
#endif
        }

        private void WriteLog(string msg)
        {
            System.Diagnostics.Trace.Write(msg);
        }

        #region Find<TEntity>
        /// <summary>
        /// Finds the specified key values.
        /// </summary>
        /// <param name="keyValues">The key values.</param>
        /// <returns>`0.</returns>
        public TEntity Find(object[] keyValues)
        {
            return base.Find<TEntity>(keyValues);
        }
        #endregion

        #region GetAll<TEntity>

        /// <summary>
        /// Gets all entiies.
        /// </summary>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetAll()
        {
            return base.GetAll<TEntity>();
        }

        /// <summary>
        /// Gets all entities.
        /// </summary>
        /// <typeparam name="TIncludeProperty">The type of the include property.</typeparam>
        /// <param name="includePath">The include path.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetAll<TIncludeProperty>(
                Expression<Func<TEntity, TIncludeProperty>> includePath)
        {
            return base.GetAll<TEntity, TIncludeProperty>(includePath);
        }

        /// <summary>
        /// Gets all entities.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the include property2.</typeparam>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetAll<TIncludeProperty1, TIncludeProperty2>(
                Expression<Func<TEntity, TIncludeProperty1>> includePath1,
                Expression<Func<TEntity, TIncludeProperty2>> includePath2)
        {
            return base.GetAll<TEntity, TIncludeProperty1, TIncludeProperty2>(includePath1, includePath2);
        }

        /// <summary>
        /// Gets all entities.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the include property2.</typeparam>
        /// <typeparam name="TIncludeProperty3">The type of the include property3.</typeparam>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <param name="includePath3">The include path3.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetAll<TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(
                Expression<Func<TEntity, TIncludeProperty1>> includePath1,
                Expression<Func<TEntity, TIncludeProperty2>> includePath2,
                Expression<Func<TEntity, TIncludeProperty3>> includePath3)
        {
            return base.GetAll<TEntity, TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(includePath1, includePath2, includePath3);
        }

        #endregion

        #region Get<TEntity>

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate)
        {
            return base.Get<TEntity>(predicate);
        }

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty">The type of the Include property.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="includePath">The include path.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> Get<TIncludeProperty>(
                Expression<Func<TEntity, bool>> predicate,
                Expression<Func<TEntity, TIncludeProperty>> includePath)
        {
            return base.Get<TEntity, TIncludeProperty>(predicate, includePath);
        }

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the Include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the Include property2.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> Get<TIncludeProperty1, TIncludeProperty2>(
                Expression<Func<TEntity, bool>> predicate,
                Expression<Func<TEntity, TIncludeProperty1>> includePath1,
                Expression<Func<TEntity, TIncludeProperty2>> includePath2)
        {
            return base.Get<TEntity, TIncludeProperty1, TIncludeProperty2>(predicate, includePath1, includePath2);
        }

        /// <summary>
        /// Gets the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the Include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the Include property2.</typeparam>
        /// <typeparam name="TIncludeProperty3">The type of the Include property3.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <param name="includePath3">The include path3.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> Get<TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(
                Expression<Func<TEntity, bool>> predicate,
                Expression<Func<TEntity, TIncludeProperty1>> includePath1,
                Expression<Func<TEntity, TIncludeProperty2>> includePath2,
                Expression<Func<TEntity, TIncludeProperty3>> includePath3)
        {
            return base.Get<TEntity, TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(predicate, includePath1, includePath2, includePath3);
        }
        #endregion

        #region GetPagingData
        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="sortColumn">The sort column.</param>
        /// <param name="isAsc">if set to <c>true</c> [is asc].</param>
        /// <returns>The retrieved entities.</returns>
        public IEnumerable<TEntity> GetPageableData(
            Expression<Func<TEntity, bool>> predicate,
            int pageSize,
            int pageIndex,
            string sortColumn,
            bool isAsc)
        {
            return base.GetPageableData<TEntity>(predicate, pageSize, pageIndex, sortColumn, isAsc);
        }

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty">The type of the include property.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="sortColumn">The sort column.</param>
        /// <param name="isAsc">if set to <c>true</c> [is asc].</param>
        /// <param name="includePath">The include path.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetPageableData<TIncludeProperty>(
            Expression<Func<TEntity, bool>> predicate,
            int pageSize,
            int pageIndex,
            string sortColumn,
            bool isAsc,
            Expression<Func<TEntity, TIncludeProperty>> includePath)
        {
            return base.GetPageableData<TEntity, TIncludeProperty>(predicate, pageSize, pageIndex, sortColumn, isAsc, includePath);
        }

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the include property2.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="sortColumn">The sort column.</param>
        /// <param name="isAsc">if set to <c>true</c> [is asc].</param>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <returns>The retrieved entities.</returns>
        public IEnumerable<TEntity> GetPageableData<TIncludeProperty1, TIncludeProperty2>(
            Expression<Func<TEntity, bool>> predicate,
            int pageSize,
            int pageIndex,
            string sortColumn,
            bool isAsc,
            Expression<Func<TEntity, TIncludeProperty1>> includePath1,
            Expression<Func<TEntity, TIncludeProperty2>> includePath2)
        {
            return base.GetPageableData<TEntity, TIncludeProperty1, TIncludeProperty2>(predicate, pageSize, pageIndex, sortColumn, isAsc, includePath1, includePath2);
        }

        /// <summary>
        /// Gets entities by the specified predicate.
        /// </summary>
        /// <typeparam name="TIncludeProperty1">The type of the include property1.</typeparam>
        /// <typeparam name="TIncludeProperty2">The type of the include property2.</typeparam>
        /// <typeparam name="TIncludeProperty3">The type of the include property3.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="sortColumn">The sort column.</param>
        /// <param name="isAsc">if set to <c>true</c> [is asc].</param>
        /// <param name="includePath1">The include path1.</param>
        /// <param name="includePath2">The include path2.</param>
        /// <param name="includePath3">The include path3.</param>
        /// <returns>
        /// The retrieved entities.
        /// </returns>
        public IEnumerable<TEntity> GetPageableData<TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(
            Expression<Func<TEntity, bool>> predicate,
            int pageSize,
            int pageIndex,
            string sortColumn,
            bool isAsc,
            Expression<Func<TEntity, TIncludeProperty1>> includePath1,
            Expression<Func<TEntity, TIncludeProperty1>> includePath2,
            Expression<Func<TEntity, TIncludeProperty1>> includePath3)
        {
            return base.GetPageableData<TEntity, TIncludeProperty1, TIncludeProperty2, TIncludeProperty3>(predicate, pageSize, pageIndex, sortColumn, isAsc, includePath1, includePath2, includePath3);
        }
        #endregion

        #region Save<TEntity>
        /// <summary>
        /// Saves the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void Save(TEntity entity)
        {
            base.Save<TEntity>(entity);
        }
        #endregion
    }
}
